Free Information Xchange '98 presents: Virtua Squad 2 - CD check crack by Static Vengeance Requirements: hex editor and full install Okay, time for another quick tutorial in CD check cracking. Like all my the other tutorials on CD checks you will need to use W32Dasm to follow along. Alright, first thing you need to do is to disassemble the exe file ppj2dd.exe. Now when you run the game without the CD a dialog box comes up and says you can cancel or play as a guest on the proving grounds. Well I thought that would be easy enough to find from the Refs/String data references in W32Dasm (IE: go up to the menu bar and select "Refs" and then select "String data references" from the drop down menu). However there is no direct reference to that string. But there was something even better when you scrolled down and checked out what strings are referenced. How about "VCOP2\PROJECT\PPJ2DD.EXE", that's a direct reference to the exe file on the CD with the CD volume and all. Well you should know by now that that has to be apart of the CD checking routine, right? So double clicking on that string will put you right in the middle of the routine that checks for the CD and it goes something like this: * Referenced by a CALL at Address: |:0040E4B7 | :0040E420 83EC50 sub esp, 00000050 :0040E423 53 push ebx :0040E424 56 push esi :0040E425 57 push edi :0040E426 33DB xor ebx, ebx <-- Zero out number of runs through the CD check :0040E428 55 push ebp * Reference To: KERNEL32.GetLogicalDrives, Ord:00FAh <-- This is one tip off | :0040E429 FF1510738000 Call dword ptr [00807310] :0040E42F 8BE8 mov ebp, eax * Reference To: KERNEL32.lstrcatA, Ord:0292h | :0040E431 8B350C738000 mov esi, dword ptr [0080730C] * Reference To: USER32.wsprintfA, Ord:026Dh | :0040E437 8B3D58748000 mov edi, dword ptr [00807458] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E48F(C) | :0040E43D B801000000 mov eax, 00000001 :0040E442 8ACB mov cl, bl :0040E444 D3E0 shl eax, cl :0040E446 85C5 test ebp, eax :0040E448 7441 je 0040E48B :0040E44A 8D4341 lea eax, dword ptr [ebx+41] :0040E44D 8D4C2410 lea ecx, dword ptr [esp+10] :0040E451 50 push eax * Possible StringData Ref from Data Obj ->"%c:\" <-- Commonly used ref in CD checks | :0040E452 687C974500 push 0045977C :0040E457 51 push ecx :0040E458 FFD7 call edi :0040E45A 8D4C241C lea ecx, dword ptr [esp+1C] :0040E45E 83C40C add esp, 0000000C :0040E461 51 push ecx * Reference To: KERNEL32.GetDriveTypeA, Ord:00DFh <-- Commonly used "text string" to search for | :0040E462 FF1508738000 Call dword ptr [00807308] :0040E468 83F805 cmp eax, 00000005 <-- 05 is the value for a CD-ROM drive :0040E46B 751E jne 0040E48B :0040E46D 8D442410 lea eax, dword ptr [esp+10] * Possible StringData Ref from Data Obj ->"VCOP2\PROJECT\PPJ2DD.EXE" <-- Check for this file on CD | :0040E471 6860974500 push 00459760 :0040E476 50 push eax :0040E477 FFD6 call esi :0040E479 8D442410 lea eax, dword ptr [esp+10] :0040E47D 6A00 push 00000000 :0040E47F 50 push eax * Reference To: KERNEL32._lopen, Ord:028Eh | :0040E480 FF1504738000 Call dword ptr [00807304] :0040E486 83F8FF cmp eax, FFFFFFFF :0040E489 7508 jne 0040E493 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0040E448(C), :0040E46B(C) | :0040E48B 43 inc ebx <-- Made another check, add 1 to ebx :0040E48C 83FB20 cmp ebx, 00000020 <-- Try up to 20h (32) times :0040E48F 7CAC jl 0040E43D <-- Keep trying to fid the CD until you hit 32 :0040E491 EB07 jmp 0040E49A <-- Tried 32 times and STILL didn't find it * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E489(C) | :0040E493 50 push eax * Reference To: KERNEL32._lclose, Ord:028Bh | :0040E494 FF1500738000 Call dword ptr [00807300] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E491(U) | :0040E49A B8FFFFFFFF mov eax, FFFFFFFF <-- Set up for a failed CD check :0040E49F 83FB20 cmp ebx, 00000020 <-- Did we fail to find the file 32 times? :0040E4A2 7402 je 0040E4A6 <-- The all important instruction :0040E4A4 8BC3 mov eax, ebx <-- Anything else is passed CD check * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E4A2(C) | :0040E4A6 5D pop ebp :0040E4A7 5F pop edi :0040E4A8 5E pop esi :0040E4A9 5B pop ebx :0040E4AA 83C450 add esp, 00000050 :0040E4AD C3 ret That's the section of code that checks for the program file on the CD. If the CD check failed eax is loaded with FFFFFFFF, otherwise anything else means the CD is in your CD-ROM drive... If you don't have a CD in the drive, the ONLY choice you have is to play over the modem/net or exit to Win95. So lets check out the code the calls the above routine and see what it does: * Referenced by a CALL at Address: |:0040D61A | :0040E4B0 56 push esi * Reference To: USER32.DialogBoxParamA, Ord:008Eh | :0040E4B1 8B3530748000 mov esi, dword ptr [00807430] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E4FB(C) | :0040E4B7 E864FFFFFF call 0040E420 <-- Check for original CD :0040E4BC 8B15C0B85200 mov edx, dword ptr [0052B8C0] :0040E4C2 8B0D7CB85200 mov ecx, dword ptr [0052B87C] :0040E4C8 A3D8B85200 mov dword ptr [0052B8D8], eax <-- Store the returned value :0040E4CD 83F8FF cmp eax, FFFFFFFF <-- Was it present? :0040E4D0 A1DCB85200 mov eax, dword ptr [0052B8DC] :0040E4D5 752D jne 0040E504 <-- This jump taked for passed CD check :0040E4D7 6A00 push 00000000 :0040E4D9 8B0485B8954500 mov eax, dword ptr [4*eax+004595B8] :0040E4E0 6820E54000 push 0040E520 :0040E4E5 51 push ecx :0040E4E6 50 push eax :0040E4E7 52 push edx :0040E4E8 FFD6 call esi :0040E4EA 8B0D48964500 mov ecx, dword ptr [00459648] :0040E4F0 85C0 test eax, eax :0040E4F2 7405 je 0040E4F9 :0040E4F4 83F902 cmp ecx, 00000002 <-- Hit cancel, so set up to quit to Win95 :0040E4F7 7412 je 0040E50B * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E4F2(C) | :0040E4F9 85C0 test eax, eax :0040E4FB 75BA jne 0040E4B7 <-- Loop up and retry to read for the CD :0040E4FD B8FFFFFFFF mov eax, FFFFFFFF <-- Play as the guest in the multiplayer :0040E502 5E pop esi <-- mode of the "Proving Gounds" :0040E503 C3 ret * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E4D5(C) | :0040E504 B801000000 mov eax, 00000001 <-- Everything is good, let the user PLAY! :0040E509 5E pop esi :0040E50A C3 ret * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040E4F7(C) | :0040E50B 33C0 xor eax, eax <-- Set up for exit to Win95 :0040E50D 5E pop esi :0040E50E C705D8B8520000000000 mov dword ptr [0052B8D8], 00000000 :0040E518 C3 ret Okay, there are four possible choices from the CD checking rountine. First choice is the CD is there and everything is just fine: eax is loaded with 00000001. However the other three choices come into play if no CD is found. You either retry to read the CD in which case the code simply loops back up and tries again. You can choose to play as a guest in the multi- player mode on the proving grounds: eax is loaded with FFFFFFFF, or you hit cancel and you're booted back to Win95: eax is zeroed out. So once agian we trace the program further back and take a look at the calling code to see what it does: -- Program Code -- * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040D5E5(C) | :0040D60B E8C0110000 call 0040E7D0 :0040D610 E82BFD0100 call 0042D340 :0040D615 A344964500 mov dword ptr [00459644], eax :0040D61A E8910E0000 call 0040E4B0 <-- Do CD check :0040D61F A340964500 mov dword ptr [00459640], eax <-- Store returned value here :0040D624 83F8FF cmp eax, FFFFFFFF <-- What happenned with CD check? :0040D627 0F840D030000 je 0040D93A <-- No CD, but play as guest :0040D62D 8BBC24B0000000 mov edi, dword ptr [esp+000000B0] <-- Continue with program :0040D634 8D442410 lea eax, dword ptr [esp+10] :0040D638 33DB xor ebx, ebx :0040D63A 893DC0B85200 mov dword ptr [0052B8C0], edi :0040D640 897C2428 mov dword ptr [esp+28], edi :0040D644 6A7B push 0000007B :0040D646 57 push edi * Reference To: USER32.LoadIconA, Ord:017Ch | :0040D647 8B2D00748000 mov ebp, dword ptr [00807400] -- More Program Code -- This is the section of code we want to deal with right here. This is the only call to the CD check routine (from 40D61A) and then the program code decides what to do with the value that was returned from the CD check. What I thought would be a good crack for this game was to change the Call 0040E4B0 to mov eax,00000001. That way the CD check is never made and the 00000001 in eax simulates a successful CD check. I made the patch to the program file and tested it. All functions work and it never cares if you have the CD in the CD-ROM drive or not. Make the edit to the file ppj2dd.exe and you have cracked this one. The only other thing I did was rename the file to VirtuaCop.exe and changed the Win95 shortcut to match. Edit ppj2dd.exe at offset 51,738 ================================ Search for: E8 91 0E 00 00 chagne to : B8 01 00 00 00 That's all it takes to FiX Virtua Squad 2 Static Vengeance